Skip to content

Port Sylius 2 and Symfony 7.4 with PHP 8.2 enhancements - #41

Open
Jgrasp wants to merge 1 commit into
masterfrom
sylius-2
Open

Port Sylius 2 and Symfony 7.4 with PHP 8.2 enhancements#41
Jgrasp wants to merge 1 commit into
masterfrom
sylius-2

Conversation

@Jgrasp

@Jgrasp Jgrasp commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Context

The plugin did not boot on Sylius 2. The resource component namespaces moved, the resource and routing configuration formats changed, and the admin UI switched from Semantic UI to Bootstrap 5 / Tabler — so every template shipped by the plugin rendered unstyled or broken.

This PR ports the whole plugin to Sylius 2 / Symfony 7.4 / PHP 8.2.

Before After
php ^7.4 || ^8.1 ^8.2
sylius/sylius ^1.10 ^2.0
symfony/* (implicit) ^7.4

Foundation

  • declare(strict_types=1) across all of src/
  • Resource namespace migration: Sylius\Component\Resource\*Sylius\Resource\* (Model\ResourceInterface, Factory\FactoryInterface, Doctrine\Persistence\RepositoryInterface), FQCNs resolved against sylius/resource 2.2

Configuration

  • sylius_resource.yaml: dropped form from classes (removed in Sylius 2), and registered ContentRepository on the content resource — the admin contents grid needs createListQueryBuilder(), which was missing and produced createListQueryBuilder undefined on /admin/acb/contents/
  • admin_routing.yaml: @SyliusAdmin/shared/crud templates, form moved to the route level. The two custom controllers keep being referenced by their service id (sherlockode_sylius_acb.controller.scope and .preview); both services are declared public: true, so ContainerControllerResolver resolves them as-is and no FQCN alias is needed
  • ScopeInitCommand is declared in a dedicated commands.xml, imported by config.yaml

PHP modernisation

  • PreviewController, ScopeController, AdminVersionListener, AdminGridListener: constructor property promotion, native types, redundant phpdoc removed
  • ScopeInitCommand: execute(): int. The command name and description stay in configure() rather than in an attribute — a plugin cannot presume that the host application autoconfigures its services, and the service is already tagged console.command

Admin templates (Semantic UI → Bootstrap 5 / Tabler)

  • Page/_form, Content/_form, Page/_preview: BS5 grids, cards and accordions; form context resolved through hookable_metadata
  • Tabs macro: nav-tabs driven by the BS5 data API — the jQuery .tab() call is gone, no JS needed
  • classes / collapse macros: Semantic UI utility classes → BS5 / Tabler
  • tools.html.twig: BS5 cards, body block and the Sylius 2 admin layout
  • Form themes: @SyliusUi/Form/theme@SyliusAdmin/shared/form_theme
  • Status badges use Tabler variants (bg-*-lt)
  • acb-notification.js: native BS5 modal replacing Semantic UI + the jQuery global (both absent from Sylius 2), with a new admin/_confirmation_modal.html.twig template and a window.confirm() fallback when the markup is not rendered
  • admin/stylesheets.html.twig removed: it only pulled the jQuery UI CSS from an external CDN, and the sylius_ui block that injected it on the four admin screens no longer exists in Sylius 2. Nothing referenced the template any more. The jquery-ui sortable JS the builder relies on stays bundled by the application

Bug fixes surfaced along the way

Doctrine ORM 3 TypeError on scoped modals. getByScopeQueryBuilder() passed a bare PHP array to QueryBuilder::setParameters(), which ORM 3 rejects (it requires an ArrayCollection). The exception was thrown before any Twig rendering, so every scoped ACB modal (acb_content_modal) returned a guaranteed HTTP 500 as soon as the scope was resolved — and scopes.enabled is hardcoded to true by SherlockodeSyliusAdvancedContentExtension, making it systematic in production. Replaced with two successive setParameter() calls, a form valid under both ORM 2 and 3. PageRepository carried the same latent defect (not reachable today, since regular ACB page scopes are always null) and was fixed in the same pass.

Inert Gedmo traits on Page. Since the annotations → XML conversion in v0.4.0, the TimestampableEntity / BlameableEntity traits had no effect: the XML driver does not inspect PHP attributes on traits. Page.orm.xml imported the gedmo namespace without ever using it, so created_at / updated_at / created_by / updated_by were unmapped — doctrine:migrations:diff wanted to DROP them and timestampable stopped being maintained. The four fields are now declared explicitly with <gedmo:timestampable> / <gedmo:blameable> tags, the way Sylius core does for its XML-mapped entities. Types match the existing schema (created_at / updated_at datetime NOT NULL, created_by / updated_by string(255) nullable).

Breaking change

This branch targets Sylius 2 exclusively — it drops support for Sylius 1.x, PHP 7.4 and PHP 8.1. It warrants a new major (or 2.x) release line rather than a patch on the current one.

Verification

The two bug fixes above were found and fixed during manual QA on a Sylius 2 application, which is also how the routing, resource and controller wiring was exercised (contents and pages grids, page and content forms, preview, tools page, scoped content modals).

The command registration and controller wiring were re-checked on that application after the review round: bin/console list still exposes sherlockode:sylius-acb:init-scope without the attribute, the command runs, router:match /admin/acb/scope/init resolves sherlockode_sylius_acb.controller.scope::updateScopesAction(), and lint:container passes.

No automated test suite covers these paths in the plugin, so reviewers should keep in mind:

  • the ported templates have no regression coverage — visual checks only
  • the quickest confirmation for the Page mapping is running doctrine:migrations:diff on a Sylius 2 application and checking the diff comes out empty

@Jgrasp
Jgrasp marked this pull request as draft July 28, 2026 12:49
Comment thread src/Command/ScopeInitCommand.php Outdated
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Contracts\Translation\TranslatorInterface;

#[AsCommand(name: 'sherlockode:sylius-acb:init-scope', description: 'Initialize Sylius scopes for ACB')]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On est dans un plugin. Pas d'attribute, mettre la déclaration dans un fichier xml propre.

sherlockode_sylius_acb_admin_scope_init:
path: "/scope/init"
defaults:
_controller: sherlockode_sylius_acb.controller.scope::updateScopesAction

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sherlockode_sylius_acb.controller.scope pourquoi on ne peut plus utiliser ça ? Normalement c'est toujours disponible.

sherlockode_sylius_acb_admin_page_preview:
path: "/preview/{pageIdentifier}"
defaults:
_controller: sherlockode_sylius_acb.controller.preview::previewAction

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idem ici

Comment thread src/Resources/config/events.yaml Outdated
blocks:
sylius_acb:
template: "@SherlockodeSyliusAdvancedContentPlugin/admin/stylesheets.html.twig"
# sylius_ui.events was removed in Sylius 2.x (replaced by Twig UX hooks).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Supprime les commentaires

Comment thread src/Resources/config/services.yaml Outdated
tags:
- { name: container.service_subscriber }

# FQCN aliases: admin_routing.yaml référence ces contrôleurs par leur FQCN

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pas de commentaire

Comment thread src/Resources/config/services.yaml Outdated
# FQCN aliases: admin_routing.yaml référence ces contrôleurs par leur FQCN
# (_controller: ...\PreviewController::previewAction). Le resolver Symfony cherche
# un service dont l'id == FQCN ; sans cet alias il tente un new() sans DI → "not in container".
Sherlockode\SyliusAdvancedContentPlugin\Controller\PreviewController:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normalement pas besoin car c'est un resource controller. Donc l'alias est mis automatiquement. Si ça fonctionnne pas c'est pas normal

The plugin did not boot on Sylius 2: the resource component namespaces
moved, the resource and routing configuration formats changed, and the
admin UI switched from Semantic UI to Bootstrap 5 / Tabler, so every
template shipped by the plugin rendered unstyled or broken.

Requirements move to php ^8.2, sylius/sylius ^2.0 and symfony ^7.4. This
drops support for Sylius 1.x, PHP 7.4 and PHP 8.1, and warrants a new
major release line rather than a patch on the current one.

Foundation
- declare(strict_types=1) across src/
- resource namespaces: Sylius\Component\Resource\* -> Sylius\Resource\*
- constructor property promotion and native types on controllers and
  listeners, redundant phpdoc removed

Configuration
- sylius_resource.yaml: form dropped from classes, removed in Sylius 2;
  ContentRepository registered on the content resource so the admin
  contents grid gets the createListQueryBuilder() it was missing
- admin_routing.yaml: @SyliusAdmin/shared/crud templates, form moved to
  the route level
- ScopeInitCommand declared in a dedicated commands.xml

Admin templates, Semantic UI to Bootstrap 5 / Tabler
- Page and Content forms, preview and tools pages rebuilt on BS5 grids,
  cards and accordions, form context resolved through hookable_metadata
- tabs driven by the BS5 data API, no jQuery call left
- form themes: @SyliusUi/Form/theme -> @SyliusAdmin/shared/form_theme
- status badges use Tabler variants
- acb-notification.js uses a native BS5 modal, with a new
  admin/_confirmation_modal.html.twig and a window.confirm() fallback
  when the markup is not rendered
- admin/stylesheets.html.twig removed: it only pulled the jQuery UI CSS
  from an external CDN, and the sylius_ui block that injected it no
  longer exists in Sylius 2

Bug fixes surfaced along the way
- Doctrine ORM 3 TypeError on scoped modals. getByScopeQueryBuilder()
  passed a bare PHP array to QueryBuilder::setParameters(), which ORM 3
  rejects. The exception was thrown before any Twig rendering, so every
  scoped content modal returned a guaranteed HTTP 500 as soon as the
  scope was resolved, and scopes are enabled by default. Replaced with
  successive setParameter() calls, valid under both ORM 2 and 3.
  PageRepository carried the same latent defect and was fixed too.
- Inert Gedmo traits on Page. Since the annotations to XML conversion,
  the XML driver never inspected the attributes carried by the
  TimestampableEntity and BlameableEntity traits, leaving created_at,
  updated_at, created_by and updated_by unmapped: migrations:diff wanted
  to drop them and timestampable stopped being maintained. The four
  fields are now declared explicitly with gedmo:timestampable and
  gedmo:blameable tags, the way Sylius core does for XML-mapped
  entities.
@Jgrasp
Jgrasp marked this pull request as ready for review July 28, 2026 13:38
@Jgrasp
Jgrasp requested review from BrownSim and sophie-mulard July 28, 2026 13:39
{% for code, name in channels %}
{% if channels|length > 1 %}
<h5>{{ name }}</h5>
<h6 class="mb-2">{{ name }}</h6>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ici on change (pas bcp) le style

Comment thread src/Resources/config/sylius_resource.yaml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants